package observer

import (
	"container/list"
	"fmt"
)

type Subject interface {
	RegisterObserver(o Observer)
	RemoveObserver(o Observer)
	NotifyObserver()
}

type Observer interface {
	Update()
}

type DisplayElement interface {
	Display()
}

/////////////////////////////////////

type WeatherData struct {
	o *list.List
	t int // temperature
	h int // humidity
	p int // pressure
}

func NewWeatherData() *WeatherData {
	r := new(WeatherData)
	r.o = new(list.List)
	return r
}

func (o *WeatherData) RegisterObserver(ob Observer) {
	o.o.PushBack(ob)
}

func (o *WeatherData) RemoveObserver(ob Observer) {
	for e := o.o.Front(); e != nil; e = e.Next() {
		if e.Value == ob {
			o.o.Remove(e)
			return
		}
	}
}

func (o *WeatherData) NotifyObserver() {
	for e := o.o.Front(); e != nil; e = e.Next() {
		e.Value.(Observer).Update()
	}
}

//////////////////////////////////////

type CurrentConditionsDisplay struct {
}

func (o *CurrentConditionsDisplay) Update() {
	o.Display()
}

func (o *CurrentConditionsDisplay) Display() {
	fmt.Println("CurrentConditionsDisplay update!")
}

type StatisticsDisplay struct {
}

func (o *StatisticsDisplay) Update() {
	o.Display()
}

func (o *StatisticsDisplay) Display() {
	fmt.Println("StatisticsDisplay update!")
}

type ForecastDisplay struct {
}

func (o *ForecastDisplay) Update() {
	o.Display()
}

func (o *ForecastDisplay) Display() {
	fmt.Println("ForecastDisplay update!")
}

type ThirdPartyDisplay struct {
}

func (o *ThirdPartyDisplay) Update() {
	o.Display()
}

func (o *ThirdPartyDisplay) Display() {
	fmt.Println("ThirdPartyDisplay update!")
}
